<?php
/**
 * Copyright (c) 2010, Slawomir Mazur <mazursllawek@gmail.com>
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions 
 * are met:
 * 
 * o Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer.
 * o Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * o Neither the name of the Softisland nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * Enter description here...
 *
 * @package     Admin
 * @subpackage  Admin_Library
 * @copyright   Slawomir Mazur (c) 2010 (http://www.zend.com/zce.php?c=ZEND011643)
 * @license     http://www.opensource.org/licenses/bsd-license.php
 * @author      Slawomir Mazur <mazursllawek@gmail.com>
 */

class Admin_LibraryController extends Zend_Controller_Action
{    
	const FORM_GROUP_NAME = 'library';
	
	protected $_reader = null;
	
	protected $_library = null;
	
	/**
	 * 
	 * Load collection of uploaded files
	 */
    public function indexAction()
    {
    	$libraries = Gp_App::getModel('system/library')->getCollectionSql();

    	$page = (int) $this->getRequest()->getParam('page', 1);
    	$librariesCollection = new Zend_Paginator(
			new Zend_Paginator_Adapter_DbSelect($libraries)
		);

		$librariesCollection->setCurrentPageNumber($page);

    	$this->view->collection = $librariesCollection;
    }
    
    public function clearCacheAction() 
    {
    	$this->_helper->viewRenderer->setNoRender();
    	$response = array();
    	
    	try {
	    	// clear cache
	    	foreach (Gp_Cache_Manager::getPageCacheObject()
	    				->getIdsMatchingTags(array(System_Model_History::CACHE_TAGS)) as $id) {
	
	    		Gp_Cache_Manager::getPageCacheObject()->remove($id);
	    	}
	    	$response = array(
	    		'message' => 'Cache cleared',
	    		'status' => Gp_Controller_Action_Helper_Messenger::SUCCESS
	    	);
	    	
    	} catch (Exception $e) {
    		$response = array(
	    		'message' => $e->getMessage(),
	    		'status' => Gp_Controller_Action_Helper_Messenger::ERROR
	    	);
    	}
    	
    	if ($this->getRequest()->isXmlHttpRequest()) {
    		$this->_helper->layout()->disableLayout();
    		$this->getResponse()->clearBody();
    		
			$this->getResponse()->setBody(Zend_Json::encode($response));
    		return;
    	} else {
			$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
						->addMessage($response['message'], $response['status']);
    		$this->_redirect('admin/library');
    	}
    }
    
    /**
     * 
     * Create read form for selected file
     */
    public function readAction()
    {
    	if (!($id = $this->getRequest()->getParam('id', false))) {
    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    				->addError($this->view->translate('Wrong id specified'));
    		$this->_redirect('admin/library');
    	}
    	
    	try {
    		$library = Gp_App::getModel('system/library')->getLibraryById($id);
    		
    		// load Levenshtein algorithm
    		$view = $this->view;
    		$view->headScript()->appendFile($view->baseUrl('js/levenshtein.js'));
    		
    		// some basic view settings
    		$this->view->libraryId = $library->library_id;
    		$this->view->company = $library->company_id;
    		
    	} catch (Exception $e) {
    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    				->addError($this->view->translate($e->getMessage()));
    		$this->_redirect('admin/library');
    	}
    }
    
    /**
     * 
     * Read selected file
     */
    public function readPostAction()
    {
    	$this->_helper->viewRenderer->setNoRender();
    	
    	if (!$this->getRequest()->isPost() || 
    			!$this->getRequest()->getParam(self::FORM_GROUP_NAME, false)) { 
    		
    		$this->_redirect('admin/library');
    	}
    	
    	$form = $this->_getReadForm();
    	$data = $this->getRequest()->getParam(self::FORM_GROUP_NAME, array());
    	
    	if ($form->isValid($data)) {
    		try {
    			// csv file parser
	    		$parser = new Gp_File_Csv($data['id']);
	    		// gene_id column index
	    		//$parser->setGeneIdColumn($data['geneid']);
	    		
	    		// create and add some row filter if necessary
	    		switch ((int) $data['rows']) {
	    			case 1: $parser->setLoadWhole(true);
	    				break;
	    			case 2: $parser->setRowsToRead($data['rows-opts']);
	    				break;
	    			case 3: $parser->setRowsToOmit($data['rows-opts']);
	    				break;
	    			case 4: $parser->setStartRow((int) $data['rows-opts']);
	    				break;
	    			case 5: $parser->setEndRow((int) $data['rows-opts']);
	    			default:
	    				break;
	    		}
	    		
	    		// create and add some column filter if necessary
	    		if (2 == $data['cols']) {
	    			if (!isset($data['map'])) {
	    				throw new Exception('Columns map not available');
	    				return;
	    			}
	    			
	    			$parser->setColumnsMapper($data['map']);
	    			$parser->setColumnsToRead($data['map']['file']);
	    		}
	    		// set csv extras
	    		$parser->setDelimiter($data['value-delimiter'])
	    				->setEnclosure($data['value-encloser']);
	    			    		
	    		$startTime = microtime(true);
	    		$parser->parse();
	    		$endTime = microtime(true);

	    		$library = $parser->getFileInstance();
	    		$library->status = System_Model_Library::READED;
	    		$library->save();
	    		
	    		// clear cache
	    		foreach (Gp_Cache_Manager::getPageCacheObject()
	    					->getIdsMatchingTags(array(System_Model_History::CACHE_TAGS)) as $id) {

	    			Gp_Cache_Manager::getPageCacheObject()->remove($id);
	    		} 
	    		
	    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
	    				->addSuccess('Execution time: ' . sprintf('%.4f', $endTime - $startTime) . ' seconds');
	    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
	    				->addNotice('Library changed status for: Readed');
				$this->_redirect('admin/library/read/id/' . $data['id']);
				
    		} catch (Exception $e) {
    			Gp_App::logException($e);
    			$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    					->addError($e->getMessage());
				$this->_redirect('admin/library/read/id/' . $data['id']);
    		}
    	} else {
    		$allMessages = (array) $form->getMessages(self::FORM_GROUP_NAME, true);
    		foreach ($allMessages as $filed => $messages) {
    			if (is_array($messages) && (count($messages) > 0)) {
    				foreach ($messages as $message) {
    					$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    							->addError($message);
    				}
    			}
    		}
    		
    		$this->_redirect('admin/library');
    	}
    }
    
    /**
     * 
     * Edit library data
     */
    public function editAction()
    {
    	if (!($id = $this->getRequest()->getParam('id', false))) {
    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    			->addError($this->view->translate('Wrong id specified'));
    		$this->_redirect('admin/library');
    	}
    	
    	// load date picker
    	$view = $this->view;
    	$view->headLink()->appendStylesheet($view->baseUrl('js/datepicker/css/bootstrap.css'));
    	$view->headLink()->appendStylesheet($view->baseUrl('js/datepicker/css/datepicker.css'));
    	
    	$view->headScript()->appendFile($view->baseUrl('js/datepicker/js/prettify.js'));
    	$view->headScript()->appendFile($view->baseUrl('js/datepicker/js/jq.js'));
    	$view->headScript()->appendFile($view->baseUrl('js/datepicker/js/datepicker.js'));
    	
    	try {
    		$library = Gp_App::getModel('system/library')->getLibraryById($id);
    		
    		$form = $this->_getEditForm();
    		
    		// fix dates
    		$library->created_at = date('Y-m-d', strtotime($library->created_at));
    		$library->designed_at = date('Y-m-d', strtotime($library->designed_at));
    		
	    	$form->populate($library->toArray());
	    	$form->getElement('library_id')->setValue($library->library_id);
	    	
	    	$this->view->form = $form;
    		
    	} catch (Exception $e) {
    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    				->addError($this->view->translate($e->getMessage()));
    		$this->_redirect('admin/library');
    	}
    }
    
    /**
     * 
     * Save library data
     */
    public function editPostAction()
    {
    	$this->_helper->viewRenderer->setNoRender();
    	
    	if (!$this->getRequest()->isPost() || 
    			!$this->getRequest()->getParam(self::FORM_GROUP_NAME, false)) {
    			 
    		$this->_redirect('admin/library');
    	}
    	
    	$data = $this->getRequest()->getParam(self::FORM_GROUP_NAME, array());
    	
    	try {
    		$id = (int) @$data['library_id'];
    		
    		$library = Gp_App::getModel('system/library')->find($id)->current();
    		$library->created_at = $data['created_at'];
    		$library->designed_at = $data['designed_at'];
    		$library->provider = $data['provider'];    		
    		$library->company_id = (int) $data['company_id'];
    		$library->comment = empty($data['comment'])? null : (string) $data['comment'];
    		$library->status = (int) $data['status'];    		
    		$library->save();
    		
    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    				->addSuccess('Library was saved successfully');
    		$this->_redirect('admin/library/edit/id/' . $id);
    	} catch (Exception $e) {
    		$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
    				->addError($this->view->translate($e->getMessage()));
    		$this->_redirect('admin/library');
    	}
    }
    
    public function deleteAction()
    {
    	$this->_helper->viewRenderer->setNoRender();
    	
    	if (!$this->getRequest()->isPost() || 
    		!($id = $this->getRequest()->getParam('id', null))) {
    			 
    		$this->_redirect('admin/library');
    	}
    	
    	// response
    	$response = array();
    	
    	try {
    		$library = Gp_App::getModel('system/library')->find((int) $id)->current();

    		$file = new Gp_Io_File();
    		$file->cd(Gp_File_Excel::BASIC_EXCEL_UPLOAD_PATH);
			$file->rm($library->name);

			$library->delete();

    		$response = array(
    			'message' => $this->view->translate('Library was deleted successfully'),
    			'status' => Gp_Controller_Action_Helper_Messenger::SUCCESS
    		);
    	} catch (Exception $e) {
    		$response = array(
    			'message' => $e->getMessage(),
    			'status' => Gp_Controller_Action_Helper_Messenger::ERROR
    		);
    	}

    	if ($this->getRequest()->isXmlHttpRequest()) {
    		$this->_helper->layout()->disableLayout();
    		$this->getResponse()->clearBody();
    		
			$this->getResponse()->setBody(Zend_Json::encode($response));
    		return;
    	} else {
			$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
					->addMessage($response['message'], $response['status']);
    		$this->_redirect('admin/dashboard/upload');
    	}
    }
    
    public function loadDocumentColumnNamesAction()
    {
    	$this->_helper->viewRenderer->setNoRender();
    	
    	if ($this->getRequest()->isXmlHttpRequest()) {
    		$this->_helper->layout()->disableLayout();
    		$this->getResponse()->clearBody();
			
    		try {
    			$params = $this->getRequest()->getParam('library', array());
    			
    			if (empty($params) || (count($params) < 3)) {
    				throw new Exception('To less parameters specified');
    			}
    			
    			$parser = new Gp_File_Csv($params['id']);
    			$parser->setDelimiter($params['value-delimiter'])
    					->setEnclosure($params['value-encloser']);
    					
    			$data = $parser->getDocumentColumnNames();
    			
    			$response = array(
    				'columns' => $data,
    				'status' => Gp_Controller_Action_Helper_Messenger::SUCCESS
    			);
    		} catch (Exception $e) {
    			$response = array(
    				'message' => $this->view->translate($e->getMessage()),
    				'status' => Gp_Controller_Action_Helper_Messenger::ERROR
	    		);
	    		Gp_App::logException($e);
    		}
    		
    		$this->getResponse()->setBody(Zend_Json::encode($response));
    		return;
    	} else {
    		// TODO: do something with that
			$this->_helper->getHelper(Gp_View_Helper_Messenger::ADMIN_MESSENGER)
					->addError($this->view->translate('Wrong request'));
			$this->_redirect('admin/library/read');
    	}
    }
    
    protected function _getReadForm()
    {
    	$form = new Gp_Form();
    	$form->setAction($this->view->baseUrl('admin/library/read-post'))
			 ->setAttrib('enctype', 'multipart/form-data')
			 ->setMethod('post')
			 ->setAttrib('id', 'rnaiRead')
			 ->setButtonsToReset(array('submit'))
			 ->setElementsBelongTo(self::FORM_GROUP_NAME);
    	
		$rows = new Zend_Form_Element_Select(Gp_View_Helper_Reader::ROWS_FIELD_ID);
		$rows->setLabel('Read rows')
				->setMultiOptions($this->getReader()->getRowsOptions())
				->setAttrib('class', 'required') 
				->setRequired(true);

		$rowOptions = new Zend_Form_Element_Text(Gp_View_Helper_Reader::ROWS_FIELD_ID . '_opts');
		$rowOptions->setLabel('Row ids');
				
		$libraryId = new Zend_Form_Element_Hidden('id');
		$libraryId->setRequired(true);
				
    	$submit = new Zend_Form_Element_Submit('submit');
    	
        $form->addElements(array($rows, $rowOptions, $libraryId, $submit));
        
    	return $form;
    }
    
    protected function _getEditForm()
    {
    	$form = new Gp_Form();
    	$form->setAction($this->view->baseUrl('admin/library/edit-post'))
			 ->setMethod('post')
			 ->setAttrib('id', 'rnaiEdit')
			 ->setButtonsToReset(array('submit', 'cancel', 'delete'))
			 ->setElementsBelongTo(self::FORM_GROUP_NAME);
    	
		$name = new Gp_Form_Element_Xhtml('name');
		$name->setLabel('Library name');
			 
		$companies = new Zend_Form_Element_Select('company_id');
		$companies->setLabel('Company')
				->setMultiOptions($this->getLibraryHelper()->getCompanies())
				->setAttrib('class', 'required') 
				->setRequired(true);

		$comment = new Zend_Form_Element_Textarea('comment');
		$comment->setLabel('Comment')
				->setAttrib('cols', '15')
        	   	->setAttrib('rows', '5');
				
        $status = new Zend_Form_Element_Select('status');
		$status->setLabel('Status')
				->setMultiOptions($this->getLibraryHelper()->getStatuses())
				->setAttrib('class', 'required') 
				->setRequired(true);

		$createdAt = new Zend_Form_Element_Text('created_at');
		$createdAt->setLabel('Created at')
				->setAttrib('class', 'required input-text')
				->setRequired(true);

		$designedAt = new Zend_Form_Element_Text('designed_at');
		$designedAt->setLabel('Designed at')
				->setAttrib('class', 'required input-text')
				->setRequired(true);		

		$provider = new Zend_Form_Element_Text('provider');
		$provider->setLabel('Provided by')
				->setAttrib('class', 'input-text');
				
		$libraryId = new Zend_Form_Element_Hidden('library_id');
		$libraryId->setRequired(true);
				
    	$submit = new Zend_Form_Element_Button('submit');
    	$submit->setAttrib('class', 'action')
    			->setAttrib('type', 'submit');
    	
    	$cancel = new Zend_Form_Element_Button('cancel');
    	$cancel->setAttrib('class', 'action');
    	
        $delete = new Zend_Form_Element_Button('delete');
		$delete->setAttrib('type', 'submit');
    	
        $form->addElements(array($name, $createdAt, $designedAt, $provider, 
        	$companies, $comment, $status, $libraryId, $submit, $cancel, $delete));
        
    	return $form;
    }
    
    /**
     * Load uploader helper
     * 
     * @return Gp_View_Helper_Reader
     */
    public function getReader()
    {
    	if (is_null($this->_reader)) {
    		$this->_reader = new Gp_View_Helper_Reader();
    	}
    	
    	return $this->_reader;
    }
    
    /**
     * Load library helper
     * 
     * @return Gp_View_Helper_Library
     */
    public function getLibraryHelper()
    {
    	if (is_null($this->_library)) {
    		$this->_library = new Gp_View_Helper_Library();
    	}
    	
    	return $this->_library;
    }
}